home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / shellxas.zip / SHELLX.ASM next >
Assembly Source File  |  1993-06-20  |  34KB  |  985 lines

  1. ;[*************************************************************************]
  2. ;[*************************************************************************]
  3. ;[*                                                                       *]
  4. ;[*                                                                       *]
  5. ;[*                                                                       *]
  6. ;[*    Copyright (C) 1991 by Borland International                        *]
  7. ;[*    All rights reserved                                                *]
  8. ;[*                                                                       *]
  9. ;[*    Written by Jeffrey J. Peters                                       *]
  10. ;[*                                                                       *]
  11. ;[*    ---------------------------------------------------------------    *]
  12. ;[*                                                                       *]
  13. ;[*                                                                       *]
  14. ;[*                                                                       *]
  15. ;[*                                                                       *]
  16. ;[*************************************************************************]
  17. ;[*************************************************************************]
  18. ;
  19.  
  20. .186
  21. JUMPS
  22. LOCALS
  23.  
  24. PRGNAME       EQU 'Shellx'
  25. VER            EQU '0.50'
  26.  
  27.  
  28. ;------------------------------
  29. ; Some Macros for this program
  30. ;------------------------------
  31. mDefISR MACRO   i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,iA; Allow for 10 interrupts
  32.         IFNB    <iA>
  33.                 Error   <Too many arguments in call to mDefISR>
  34.         ENDIF
  35.         ISRTable label  WORD                    ; Label to beginning of Table
  36.         IRP     iNum,<i0,i1,i2,i3,i4,i5,i6,i7,i8,i9>
  37.                 IFB    <iNum>                   ; End of list of arguments ?
  38.                         ISRCount EQU (($ - OFFSET ISRTable) SHR 2)
  39.                         exitm
  40.                 ELSE
  41.                         Old&&iNum  label dword   ; Dword label to Old ISR
  42.                         OldISR&&iNum dw 2 dup (?); Old ISR Address
  43.  
  44.                 ENDIF
  45.         ENDM
  46. ENDM
  47. mGetISR MACRO   iseg, i0,i1,i2,i3,i4,i5,i6,i7,i8,i9   ; Allow for 10 interrupts
  48.         mov     ah, 35h                         ; GetVect Function (INT 21h)
  49.         IRP     iNum,<i0,i1,i2,i3,i4,i5,i6,i7,i8,i9>
  50.                 IFB    <iNum>                   ; End of list of arguments ?
  51.                         exitm
  52.                 ELSE
  53.         .RADIX 16      ;Use Hexadecimal - Macro ;
  54.                         mov     al, &&iNum      ; Load the ISR number in AL
  55.         .RADIX 10      ;Restore Radix to Base 10;
  56.                         int     21h             ; Call INT 21h (DOS)
  57.                         mov     &iseg:OldISR&&iNum, bx; Save ISR's Offset
  58.                         mov     &iseg:OldISR&&iNum[2], es; Save Segment
  59.                 ENDIF
  60.         ENDM
  61. ENDM
  62. mSetISR MACRO   iseg,i0,i1,i2,i3,i4,i5,i6,i7,i8,i9   ; Allow for 10 interrupts
  63.         mov     ah, 25h                         ; GetVect Function (INT 21h)
  64.         IRP     iNum,<i0,i1,i2,i3,i4,i5,i6,i7,i8,i9>
  65.                 IFB    <iNum>                   ; End of list of arguments ?
  66.                         exitm
  67.                 ELSE
  68.         .RADIX 16      ;Use Hexadecimal - Macro ;
  69.                         mov     al, &&iNum      ; Load the ISR number in AL
  70.         .RADIX 10      ;Restore Radix to Base 10;
  71.                         lea     dx, &iseg:NewISR&&iNum; Point DS:DX to our ISR
  72.                         int     21h             ; Call INT 21h (DOS)
  73.                 ENDIF
  74.         ENDM
  75. ENDM
  76. mRestoreISR     MACRO   i0,i1,i2,i3,i4,i5,i6,i7,i8,i9
  77.         mov     ah, 25h                         ; GetVect Function (INT 21h)
  78.         push    ds
  79.         IRP     iNum,<i0,i1,i2,i3,i4,i5,i6,i7,i8,i9>
  80.                 IFB    <iNum>                   ; End of list of arguments ?
  81.                         exitm
  82.                 ELSE
  83.         .RADIX 16      ;Use Hexadecimal - Macro ;
  84.                         mov     al, &&iNum      ; Load the ISR number in AL
  85.         .RADIX 10      ;Restore Radix to Base 10;
  86.                         lds     dx, cs:Old&&iNum; Point DS:DX to our ISR
  87.                         int     21h             ; Call INT 21h (DOS)
  88.                 ENDIF
  89.         ENDM
  90.         pop     ds
  91. ENDM
  92. ;...................................
  93. mPutsz          macro str
  94. ;
  95. ;    Writes out a NULL terminated string to screen
  96. ;
  97.  
  98.  
  99.                 LOCAL  again, first
  100.                 mov    si, offset str
  101.                 jmp    first
  102.  
  103.      again:
  104.                 int 29h        ; undocumented 'screen write' DOS function
  105.      first:
  106.                 lodsb
  107.                 or     al, al
  108.                 jnz    again
  109.                 endm
  110. ;...................................
  111.  
  112. mPuts           macro str
  113. ;
  114. ;    Writes out a '$' terminated string to the screen
  115. ;
  116.                 mov   dx, offset str
  117.                 mov   ah, 9
  118.                 int   21h
  119.                 endm
  120. ;-------------------------
  121. TSR_STACKSIZE     EQU     140                     ; Stack size for the TSR
  122. MY_ID             EQU     0EAh
  123. DETECT_CMD        EQU     000h
  124. UNLOAD_CMD        EQU     010h
  125.  
  126.  
  127. _TEXT           SEGMENT PARA PUBLIC 'CODE' USE16
  128.                 ASSUME CS:_TEXT
  129.                 ASSUME DS:_TEXT
  130. ORG             0100h
  131. Begin:          jmp     Start
  132. TSRStack        db  TSR_STACKSIZE dup (?)       ; TSR's stack space
  133. EndTSRStack     dw      ?                       ; End of TSR stack space
  134. _8stack         db  TSR_STACKSIZE + 20 dup (?)  ; int 8 stack
  135. _8stacksize     dw      ?
  136. _8ss            dw      ?
  137. _8sp            dw      ?
  138. PrevSS          dw      ?                       ; Foreground's Stack Segment
  139. PrevSP          dw      ?                       ; Foreground's Stack Pointer
  140. PrevPSP         dw      ?                       ; Foreground's PSP
  141. TSRPSP          dw      ?                       ; The TSR's PSP
  142. mDefISR         2F,8,9                          ; define old vect pointers
  143. ; This defines  OLDxx as the old vector to be used in calls, jmp's and
  144. ; by the mGetISR, and mSetISR macros.
  145.  
  146. _2F_flag        db 0
  147.  
  148. res_table       LABEL BYTE ;------------------------------------------------;
  149.                            ; This is the table of memory that can be copied ;
  150.                            ; to from the another copy with the -M switch    ;
  151.                            ;------------------------------------------------;
  152.  
  153. _08_flag         db 0           ;
  154. _08_count        db 1           ; current count for timer
  155. _08_max          db 18          ;
  156.  
  157. res_table_len    EQU $ - res_table
  158.  
  159. ;----------------------------------------------------------------------------
  160. NewISR8         proc    far                     ; New ISR for Timer Interrupt
  161.                 jmp     dword ptr cs:[Old8]
  162. NewISR8         endp                            ; End of INT8 ISR
  163. ;----------------------------------------------------------------------------
  164. NewISR9         proc    far                     ; New ISR for Keyboard Int
  165.                 jmp     dword ptr cs:[Old9]
  166. NewISR9         endp                            ; End of INT8 ISR
  167. ;----------------------------------------------------------------------------
  168. NewISR2F        proc    far                     ; New ISR for Mux. Int.
  169.                 cmp     ah, MY_ID
  170.                 je      do_mine
  171.                 jmp     end2F
  172. do_mine:
  173.                 cmp     al, DETECT_CMD
  174.                 je      do_detect
  175.                 cmp     al, UNLOAD_CMD
  176.                 je      do_unload
  177.                 jmp     end2F
  178.  
  179. do_detect:
  180.                 mov     al, -1
  181.                 mov     bx, cs
  182.                 jmp     end2F
  183.  
  184. do_unload:
  185.                 mRestoreISR   2F,8,9             ; reset vectors
  186.                 mov     bx, cs
  187.                 jmp     end2F
  188.  
  189. end2F:
  190.                 jmp     dword ptr cs:[Old2F]
  191. NewISR2F        endp                            ; End of INT2F ISR
  192. ;----------------------------------------------------------------------------
  193. ;[]=-=-=-=-=-=-=-=-=-=-=[ ACTUAL TSR ROUTINE...]=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]
  194. ;|   This is where control is passed when our TSR is activated... various    |
  195. ;|   things are done depending upon the requirements of the TSR.. It is      |
  196. ;|   advisable to save/restore the following: REGISTERS/STACK/PSP/DTA/XtError|
  197. ;[]=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=[]
  198. TSR             proc    near
  199.                 push    ds                      ; Save current DS value
  200.                 push    cs                      ; Set DS to the code segment
  201.                 pop     ds                      ; DS -> code segment
  202.                 assume  ds:_TEXT                ; DS -> code segment
  203.                 mov     PrevSS, ss              ; Save Foreground SS
  204.                 mov     PrevSP, sp              ; Save Foreground SP
  205.                 cli                             ; Disable interrupts
  206.                 push    cs                      ; Push CodeSeg on stack
  207.                 pop     ss                      ; SS -> code segment
  208.                 mov     sp, OFFSET EndTSRStack  ; SP -> End of TSR Stack
  209.                 sti                             ; Reenable interrupts
  210.                 push    ax                      ; Save AX register
  211.                 push    bx                      ; Save BX register
  212.                 push    cx                      ; Save CX register
  213.                 push    dx                      ; Save DX register
  214.                 push    si                      ; Save SI register
  215.                 push    di                      ; Save DI register
  216.                 push    es                      ; Save ES register
  217.                 mov     ah, 62h                 ; Func 62: Get current PID
  218.                 int     21h                     ; Call MS DOS
  219.                 mov     PrevPSP, bx             ; Save the foreground's PSP
  220.                 mov     ah, 50h                 ; Func 50: Set current PID
  221.                 mov     bx, TSRPSP              ; Load TSR's process ID
  222.                 int     21h                     ; Call MS DOS
  223.  
  224. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  225.  
  226. ;
  227. ; TSR code goes here
  228. ;
  229.  
  230. message_end:
  231. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  232. EXIT_TSR:
  233.                 mov     bx, cs:PrevPSP          ; Restore the Foreground's PSP
  234.                 mov     ah, 50h                 ; Set PIP: Function 50h
  235.                 int     21h                     ; Call MS DOS
  236.                 pop     es                      ; Restore ES register
  237.                 pop     di                      ; Restore DI register
  238.                 pop     si                      ; Restore SI register
  239.                 pop     dx                      ; Restore DX register
  240.                 pop     cx                      ; Restore CX register
  241.                 pop     bx                      ; Restore BX register
  242.                 pop     ax                      ; Restore AX register
  243.                 cli                             ; Disable interrupts
  244.                 mov     ss, cs:PrevSS           ; Restore SS register
  245.                 mov     sp, cs:PrevSP           ; Restore SP register
  246.                 sti                             ; Reenable interrupts
  247.                 pop     ds                      ; Restore DS value
  248.                 ret                             ; Return to Foreground
  249. TSR             endp
  250. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  251.  
  252. ;[]-=-=-=-=-=-=-=-=-=-[ TRANSIENT PORTION OF PROGRAM ]=-=-=-=-=-=-=-=-=-=-=-[]
  253. ;|   This is the transient portion of the TSR... All Data and Code in the    |
  254. ;|   following section is discarded upon Residency... So put everything not  |
  255. ;|   needed in memory here...                                                |
  256. ;[]-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]
  257. Transient:
  258. program         db      'SHLX'
  259. version         db      VER,'   '
  260.  
  261. verbopt         db      0
  262. modopt          db      0
  263. XMSvect         dd      ?
  264. isXMS           db      1
  265. loadhi          db      0
  266. UMBseg          dw      0
  267. XMSnone_s       db      10,13,'No XMS present.',10,13,'$'
  268. XMSfree_s       db      10,13,'Largest block avail. : '
  269. XMSfree         db      '0000 k',10,13,'$'
  270. XMSver_s        db      10,13,'XMS detected, version: '
  271. XMSmajor        db      '00.'
  272. XMSminor        db      '00  HMA free: '
  273. XMShma          db      '0'
  274.                 db      '$'
  275.  
  276. EnvFreeFail     db      10,13,'Unable to Free Environment Block',10,13,'$'
  277. title_s         db      PRGNAME,' v',VER,' Copyright (c) 1991 by Borland '
  278.                 db      'International',10,13,'$'
  279.  
  280. v_id_s          db      10,13,'Int-2F, using ID: '
  281. v_id_n          db      '00h, ','$'
  282. v_seg_s         db      "reports the resident copy's PSP is located at: "
  283. v_seg_n         db      '0000h',10,13,'$'
  284. v_2F_bad        db      'cannot find any resident copy.',10,13,'$'
  285. modified_s      db      'Resident copy has been updated',10,13,'$'
  286. loaded_s        db      7,'ERROR: ',PRGNAME,' already resident, exiting...',10,13,'$'
  287. loaded_high_s   db      'TSR is loaded high (UMB)',10,13,'$'
  288. unloaded_s      db      'Unload:   successful.',10,13,'$'
  289. no_unload_s     db      7,'ERROR: Cannot Unload TSR at this time   Code: '
  290. no_unload_s_d   db      '00',10,13,'$'
  291. UMBerror_s      db      07,'ERROR: UMB error code:'
  292. UMBerror_num    db      '00 ',10,13,'$'
  293. not_loaded_s    db      7,'ERROR: ',PRGNAME,' is not loaded at this time',10,13,'$'
  294. bad_version_s   db      7,'ERROR: A copy with a different version was found',10,13,'$'
  295. wrong_option_s  db      7,'ERROR: Unrecognized option.',10,13,'$'
  296. help_s          db      'Usage:  ',PRGNAME,' [-options]                  (xxxx means 4 hex digits)',10,10,13
  297.                 db      '-V      Verbose messages                      (default = no)',10,13
  298.                 db      '-VV     Inquire about resident copy           (default = no)',10,13
  299.                 db      '-X      Print XMS information                 (for debugging only)',10,13
  300.                 db      '-U      Load high (UMB)                       (default = no)',10,13
  301.                 db      '-R      Removes the TSR from memory           (either high or low)',10,13
  302.                 db      '-?, -h  Shows this help screen',10,13,'$'
  303.  
  304. author_s        db      10,13,"This program was written by Jeffrey J. Peters for Borland International's",10,13
  305.                 db      'technical support group.  Those who contributed are:',10,10,13
  306.                 db      '  Bruneau Babet',10,13
  307.                 db      '  Shea Anderson',10,13
  308.                 db      '  Greg MacDonald',10,13
  309.                 db      10,13,'$'
  310.  
  311. Start:
  312.                 mov     TSRPSP, es              ; Save the TSR's PSP segment
  313.                 assume  ds:_TEXT                ; DS -> Code Segment
  314.                 mov     bx, 02Ch                ; offset of env. in psp
  315.                 mov     es, cs:[bx]             ; ES -> Environment Block
  316.                 mov     ah, 49h                 ; Function 49h: Free Block
  317.                 int     21h                     ; Call MS DOS
  318.                 jnc     do_the_cmd              ; Error freeing EnvBlock
  319.  
  320.                 mPuts   EnvFreeFail             ; Print Error Message
  321.                 jmp     exit_bad
  322.  
  323. do_the_cmd:
  324.                 mPuts   title_s                 ; Print title string
  325.                 call    GetXMSEntry
  326.                 jz      @@@1
  327.                 mov     cs:[isXMS], 0
  328.  
  329. @@@1:
  330.  
  331.                 mov     ax, cs
  332.                 mov     ds, ax
  333.                 mov     es, ax
  334.                 mov     di, 5
  335.                 mov     si, offset version
  336.                 mov     cx, 5
  337.                 rep     movsb                  ; put version string in PSP
  338.  
  339.                 call    ParseCMD
  340.                 cmp     cs:[modopt], 0
  341.                 je      regular_check
  342.  
  343. check_ver:
  344.                 call    CheckInstalled
  345.                 jnz     not_loaded
  346.  
  347.                 mov     ds, bx
  348.                 push    cs
  349.                 pop     es
  350.                 mov     di, 5       ; offset into our PSP
  351.                 mov     si, 5       ; offset into res's PSP
  352.                 mov     cx, 5       ; number of bytes to compare
  353.                 repe    cmpsb       ; compare while they're equal
  354.                 jcxz    modify_res
  355.  
  356.                 push    cs
  357.                 pop     ds
  358.                 mPuts   bad_version_s
  359.                 jmp     exit_bad
  360.  
  361. modify_res:
  362.                 push    ds
  363.                 pop     es
  364.                 push    cs
  365.                 pop     ds
  366.                 mov     si, offset res_table
  367.                 mov     di, offset res_table
  368.                 mov     cx, res_table_len
  369.                 shr     cx, 1
  370.                 rep     movsw
  371.                 jnc     $ + 3
  372.                 movsb
  373.  
  374. modify_done:
  375.                 mPuts   modified_s
  376.                 jmp     exit_bad
  377.                 
  378. regular_check:
  379.                 cmp     bp, 0
  380.                 je      unload                  ; unload TSR
  381.                 je      wrong_option
  382.                 cmp     bp, 1
  383.                 je      Help                    ; print help
  384.                 cmp     bp, 2
  385.                 je      wrong_option
  386.                 cmp     bp, 4
  387.                 jae     exit_bad               ; Just exit
  388.  
  389.                 ; 3  means install
  390.  
  391.                 ; check via 2F, to see if already installed.
  392.                 call    CheckInstalled          ; ZF=1 -- installed
  393.                 jnz     load_res
  394.  
  395. already_in:
  396.                 mPuts   loaded_s
  397.                 mov     ax, 4c01h
  398.                 int     21h
  399.  
  400. temp            label   word
  401.                 dw      ?
  402.  
  403. unload:
  404.                 call    CheckInstalled           ; bx gets TSR's PSP
  405.                 jnz     not_loaded
  406.  
  407.                 mov     cs:[TSRPSP], bx         ; save TSR's PSP
  408.  
  409.                 xor     ax, ax
  410.                 mov     es, ax
  411.                 mov     ax, bx
  412.  
  413.                 mov     cs:[temp], '08'         ; test 8
  414.  
  415.                 mov     bx, 4 * 8h
  416.                 cmp     es:2[bx], ax
  417.                 jne     no_unload
  418.  
  419.                 mov     cs:[temp], '09'         ; test 9
  420.  
  421.                 mov     bx, 4 * 9h
  422.                 cmp     es:2[bx], ax
  423.                 jne     no_unload
  424.  
  425.                 mov     cs:[temp], '2F'         ; test 2F
  426.  
  427.                 mov     bx, 4 * 2fh
  428.                 cmp     es:2[bx], ax
  429.                 jne     no_unload
  430.  
  431.                 call    UnhookTSRvectors         ; now that it's save, unhook
  432.  
  433. ;
  434. ; Unload the resident TSR:
  435. ; We first set the current PSP to that of the TSR's
  436. ; then we modify the termination address of the TSR (PSP:[0Ah]) to point
  437. ; to our 'back_here' function in the transient copy.
  438. ;
  439.                 mov     bx, offset back_here    ; set terminate address
  440.                 mov     es, cs:[TSRPSP]
  441.                 mov     word ptr es:[0Ah], bx
  442.                 mov     word ptr es:2[0Ah], cs
  443.  
  444.                 push    cs             ; reset DS for us
  445.                 pop     ds
  446.                 mPuts   unloaded_s
  447.  
  448.                 mov     ah, 50h                 ; UNDOC Set PSP segment
  449.                 mov     bx, cs:[TSRPSP]         ; TSR PSP segment
  450.                 int     21h
  451.  
  452.                 mov     ax, 4C80h      ; Terminate current (TSR) Process
  453.                 int     21h            ; This jumps to back_here
  454.  
  455. no_unload:
  456.                 mov     bx, offset no_unload_s_d
  457.                 mov     ax, cs:[temp]
  458.                 xchg    al, ah
  459.                 mov     word ptr cs:[bx], ax
  460.  
  461.                 mPuts   no_unload_s
  462.                 mov     ax, 4C01h
  463.                 int     21h            ; Exit with no unload message
  464.  
  465. not_loaded:
  466.                 mPuts   not_loaded_s
  467.                 mov     ax, 4C04h
  468.                 int     21h
  469.  
  470.  
  471. back_here:
  472.                 mov     ah, 50h        ; now that we're back, restore our PSP
  473.                 mov     bx, cs
  474.                 int     21h
  475.  
  476.                 mov     ax, cs:[TSRPSP]
  477.                 cmp     ax, 0A000h
  478.                 jb      finish_unload
  479.                 call    FreeUMB
  480.                 jz      ErrorInUMB
  481.  
  482. finish_unload:
  483.  
  484.                 mov     ax, 4C00h
  485.                 int     21h            ; Now exit for real.
  486.                 
  487. CheckInstalled  proc near
  488.                 mov     ax, 256 * MY_ID
  489.                 int     2Fh
  490.                 cmp     al, -1
  491.                 ;
  492.                 ; ZF = 1 if we are already loaded else ZF = 0
  493.                 ;
  494.  
  495.                 pushf
  496.                 cmp      cs:[verbopt], 0
  497.                 je       checkopt_done
  498.  
  499.                 push     bx
  500.                 mov      ax, cs
  501.                 mov      es, ax
  502.                 mov      ax, MY_ID
  503.                 mov      di, offset v_id_n
  504.                 call     BCDwrite
  505.                 mPuts    v_id_s
  506.                 pop      bx
  507.  
  508.                 popf
  509.                 pushf
  510.                 jnz      __not_here
  511.                 push     bx
  512.                 mov      di, offset v_seg_n
  513.                 pop      ax
  514.                 push     ax
  515.                 xchg     al, ah
  516.                 call     BCDwrite
  517.                 pop      ax
  518.                 call     BCDwrite
  519.                 mPuts    v_seg_s
  520.  
  521.                 jmp      checkopt_done
  522.  
  523. __not_here:
  524.                 push     bx
  525.                 mPuts    v_2F_bad
  526.                 pop      bx
  527.  
  528. checkopt_done:
  529.                 popf
  530.                 ret
  531. CheckInstalled  endp
  532.  
  533. UnhookTSRvectors proc near
  534.                  mov    ah, MY_ID
  535.                  mov    al, UNLOAD_CMD
  536.                  int    2Fh
  537.                  ret
  538. UnhookTSRvectors endp
  539.  
  540.  
  541.  
  542. ;-----------------------------------------------------------------------------
  543. ParseCMD         proc near
  544.                  cld
  545.                  mov    bx, 0081h
  546.                  push   cs
  547.                  pop    ds
  548.                  call   near ptr _UpCase
  549.  
  550.  
  551.                  mov    bp, 3                ; ret code for Install
  552.                  cmp    byte ptr cs:[80h], 0
  553.                  je     ParseEnd
  554.                  push   cs
  555.                  pop    ds
  556.                  mov    si, 81h
  557. GetNext:
  558.                  lodsb
  559.                  cmp    al, 13
  560.                  je     ParseEnd
  561.                  cmp    al, '-'
  562.                  je     get_switch
  563.                  cmp    al, '/'
  564.                  je     get_switch
  565.                  cmp    al, ' '
  566.                  je     GetNext
  567.  
  568.                  mov    bp, 2
  569.                  jmp    ParseEnd
  570.  
  571.  
  572. get_switch:
  573.                  lodsb
  574.                  cmp    al, '?'             ; help
  575.                  je     ParseHelp
  576.  
  577.                  or     al, 60h             ; convert to lower case
  578.                  cmp    al, 'r'
  579.                  je     ParseUnl
  580.                  cmp    al, 'u'
  581.                  je     GetLoadhiOption     ; Load it high or not?
  582.                  cmp    al, 'x'
  583.                  je     GetXMSOption        ; print out XMS info
  584.                  cmp    al, 'v'
  585.                  je     GetVerboseOption    ; for verbose messages
  586.                  cmp    al, 'i'
  587.                  je     do_author           ; Author screen
  588.                  cmp    al, 'm'
  589.                  je     GetModifyOption     ; modify resident copy
  590.                  cmp    al, 'h'             ; help
  591.                  mov    bp, 1
  592.                  je     ParseEnd
  593.                  mov    bp, 2               ; Wrong option
  594.                                             ; 4 - Generic error
  595.  
  596. ParseEnd:
  597.                  ret
  598. ParseCMD         endp
  599. ;-----------------------------------------------------------------------------
  600. ParseUnl:
  601.                  mov    bp, 0
  602.                  jmp    ParseEnd
  603.  
  604. ParseHelp:       mov    bp, 1
  605.                  jmp    ParseEnd
  606.  
  607. GetModifyOption:
  608.                  mov      bp, 4
  609.                  lodsb
  610.                  mov      cs:[modopt], 0
  611.                  cmp      al, '-'
  612.                  je       GetNext
  613.                  mov      cs:[modopt], 1
  614.                  cmp      al, ' '
  615.                  je       GetNext
  616.                  cmp      al, 0dh            ; Last option
  617.                  je       ParseEnd
  618.                  mov      bp, 2              ; bad option
  619.                  jmp      ParseEnd
  620.  
  621. GetVerboseOption:
  622.                  lodsb
  623.                  mov      cs:[verbopt], 0
  624.                  cmp      al, '-'
  625.                  je       GetNext
  626.                  mov      cs:[verbopt], 1
  627.                  cmp      al, ' '
  628.                  je       GetNext
  629.                  cmp      al, 'V'
  630.                  je       do_now
  631.                  cmp      al, 0dh            ; Last option
  632.                  je       ParseEnd
  633.                  mov      bp, 2              ; bad option
  634.                  jmp      ParseEnd
  635.  
  636. do_now:
  637.                  mov      cs:[verbopt], 1
  638.                  call     CheckInstalled
  639.                  mov      bp, 4
  640.                  jmp      ParseEnd
  641.  
  642.  
  643. GetLoadhiOption:
  644.                  mov    cs:[loadhi], 1
  645.                  mov    bp, 3
  646.                  jmp    ParseEnd
  647.  
  648. GetXMSOption:
  649.                  call   PrintXMSInfo
  650.                  mov    bp, 4
  651.                  jmp    ParseEnd
  652.  
  653. do_author:
  654.                  mPuts  author_s
  655.                  mov    bp, 4
  656.                  jmp    ParseEnd
  657.  
  658. Help:
  659.                 mPuts   help_s
  660.  
  661.                 mov     ax, 4C02h
  662.                 int     21h
  663.  
  664. wrong_option:
  665.                 mPuts   wrong_option_s
  666.                 mov     ax, 4C03h
  667.                 int     21h
  668.  
  669. load_res:
  670.  
  671. test_hi_low:
  672.                 push    cs
  673.                 pop     ds
  674.  
  675.                 cmp     cs:[loadhi], 0
  676.                 je      load_low
  677.                 mov     cs:[loadhi], 0
  678.                 cmp     cs:[isXMS], 1
  679.                 jne     load_low
  680.                 mov     cs:[loadhi], 1
  681.  
  682.                 mov     ax, offset Transient      ; # of bytes to keep high
  683.                 shr     ax, 4                     ; convert to paragraphs
  684.                 call    PutCodeInUMB
  685.                 jz      ErrorInUMB
  686.                 mov     ax, cs:[UMBseg]
  687.  
  688.                 dec     ax
  689.                 mov     es, ax
  690.                 mov     di, 8
  691.                 mov     si, offset program
  692.                 mov     cx, 8 /2
  693.                 rep     movsw                     ; put prog name in UMB
  694.  
  695.                 mov     ds, cs:[UMBseg]
  696.  
  697. load_low:
  698.                 mGetISR ds, 2F, 8, 9
  699.                 mSetISR ds, 2F, 8, 9
  700.                 push     cs
  701.                 pop      ds
  702.  
  703.                 cmp     cs:[loadhi], 1
  704.                 je      exit_UMB
  705.                 mov     dx, offset Transient
  706.                 int     27h                     ; go resident
  707.  
  708.  
  709. fix_al:
  710.                 sub     al, 30h
  711.                 add     al, 'A' - 10
  712.                 jmp     do_UMB_error
  713.  
  714. fix_ah:
  715.                 sub     ah, 30h
  716.                 add     ah, 'A' - 10
  717.                 jmp     fix_ah_ret
  718.  
  719. ErrorInUMB:
  720.                 mov     ah, 0
  721.                 mov     al, bl
  722.                 shl     ax, 4
  723.                 mov     al, bl
  724.                 and     ax, 0F0Fh
  725.                 or      ax, 3030h
  726.                 cmp     ah, 39h
  727.                 ja      fix_ah
  728. fix_ah_ret:
  729.                 cmp     al, 39h
  730.                 ja      fix_al
  731.  
  732.  
  733. do_UMB_error:
  734.                 push    cs
  735.                 pop     ds
  736.                 xchg    al, ah
  737.                 mov     word ptr cs:[UMBerror_num], ax
  738.                 mPuts   UMBerror_s
  739.                 mov     cs:[loadhi], 0
  740.                 jmp     load_low
  741.  
  742. exit_bad:
  743.                 mov     ax, 4c01h
  744.                 int     21h
  745.  
  746. exit_UMB:
  747.                 mPuts   loaded_high_s
  748.                 mov     ax, 4c00h
  749.                 int     21h
  750.  
  751. ;- - - - - - - - - - - - - - - - - - -
  752. _UpCase:
  753.                 cmp     byte ptr [bx], 0
  754.                 je      @done_uc
  755.                 cmp     byte ptr [bx], 13
  756.                 je      @done_uc
  757.                 cmp     byte ptr [bx], 'a'
  758.                 jb      @redo_uc
  759.                 cmp     byte ptr [bx], 'z'
  760.                 ja      @redo_uc
  761.                 and     byte ptr [bx], 0DFh    ; lower to upper case
  762. @redo_uc:
  763.                 inc     bx
  764.                 jmp     _UpCase
  765. @done_uc:
  766.                 ret
  767. ;- - - - - - - - - - - - - - - - - - -
  768.  
  769.  
  770. ;----------------------------------------------------------------------------
  771. atoi  proc near
  772. ;
  773. ;     ax (ah:al) contains 2 ascii hex digits.
  774. ;     returns the value in ax
  775. ;     upon error, cf = 1
  776.  
  777.       clc
  778.       xor bx, bx
  779.       push ax
  780.       call one_ch
  781.       pop  ax
  782.       jc the_atoi_error
  783.       mov dx, bx
  784.       mov cl, 4
  785.       shl dx, cl
  786.       xchg al, ah
  787.       xor bx, bx
  788.       call one_ch
  789.       jc the_atoi_error
  790.       add dx, bx
  791.       mov ax, dx
  792.       jmp atoi_end
  793.  
  794. one_ch:
  795.       cmp al, '0'
  796.       jb atoi_error
  797.       cmp al, '9'
  798.       ja letter
  799.       mov bl, al
  800.       sub bl, '0'
  801.       jmp one_ch_end
  802.  
  803. letter:
  804.       cmp al, 'A'
  805.       jb atoi_error
  806.       cmp al, 'F'
  807.       ja atoi_error
  808.       mov bl, al
  809.       sub bl, 'A' - 10
  810.  
  811. one_ch_end:
  812.       clc
  813.       retn
  814.  
  815. atoi_error:
  816.       stc
  817.       retn
  818.  
  819. the_atoi_error:
  820.       stc         ; error condition
  821.  
  822. atoi_end:
  823.       ret
  824. atoi  endp
  825. ;----------------------------------------------------------------------------
  826. ;----------------------------------------------------------------------------
  827. BCDwrite proc
  828. ; AL has two BCD digits that will be written to ES:DI in ASCII form
  829.  
  830.          mov ah, al
  831.          and al, 0fh
  832.          shr ah, 4
  833.                         ; ah has MSD
  834.                         ; al has LSD
  835.          or ax, 3030h
  836.          xchg al, ah
  837.  
  838.          cmp     ah, 39h
  839.          ja      _fix_ah
  840. _fix_ah_ret:
  841.          cmp     al, 39h
  842.          ja      _fix_al
  843.  
  844.  
  845. write_it:
  846.  
  847.          stosw
  848.          ret
  849.  
  850. _fix_al:
  851.          sub     al, 30h
  852.          add     al, 'A' - 10
  853.          jmp     write_it
  854.  
  855. _fix_ah:
  856.          sub     ah, 30h
  857.          add     ah, 'A' - 10
  858.          jmp     _fix_ah_ret
  859.  
  860. BCDwrite endp
  861. ;---------------------------------------------------------------------------
  862.  
  863. GetXMSEntry     proc
  864. ;
  865. ; zf = 1 if no XMS is avail, else zf = 0
  866. ;
  867.                 mov     ax, 4300h                  ; check if XMS is avail?
  868.                 int     2Fh
  869.                 cmp     al, 80h
  870.                 jne     endXMS
  871.  
  872.                 mov     ax, 4310h                  ; get entry point
  873.                 int     2Fh
  874.                 mov     word ptr cs:[XMSvect], bx
  875.                 mov     word ptr cs:2[XMSvect],es
  876. endXMS:
  877.                 ret
  878. GetXMSEntry     endp
  879. ;----------------------------------------------------------------------------
  880. PrintXMSInfo    proc
  881. ;
  882. ; Prints out the version info and HMA status for XMS
  883. ;
  884.                 cmp     cs:[isXMS], 0
  885.                 jne     p_xms_cont
  886.                 mPuts   XMSnone_s
  887.                 ret
  888.  
  889. p_xms_cont:
  890.                 mov     ah, 0
  891.                 call    cs:[XMSvect]
  892.                 push    cs
  893.                 pop     es
  894.                 push    ax
  895.                 mov     di, offset XMSmajor
  896.                 mov     al, ah
  897.                 call    BCDwrite
  898.                 pop     ax
  899.                 mov     di, offset XMSminor
  900.                 call    BCDwrite
  901.  
  902.                 mov     ah, 07h
  903.                 call    cs:[XMSvect]
  904.                 xor     al, 1         ; invert it
  905.                 or      al, 30h
  906.                 mov     cs:[XMShma], al
  907.                 mPuts   XMSver_s
  908.  
  909.                 mov     ah, 8
  910.                 call    cs:[XMSvect]
  911.                 push    ax
  912.                 mov     di, offset XMSfree
  913.                 mov     al, ah
  914.                 call    BCDwrite
  915.                 pop     ax
  916.                 mov     di, offset XMSfree + 2
  917.                 call    BCDwrite
  918.                 
  919.                 mPuts   XMSfree_s
  920.  
  921.                 ret
  922. PrintXMSInfo    endp
  923. ;----------------------------------------------------------------------------
  924. PutCodeInUMB    proc
  925. ;
  926. ; copies the code from low memory to UMB if availible
  927. ;
  928. ; call with:
  929. ;   ax - containing the number of paragraphs to copy up to UMB
  930. ;
  931. ; returns:
  932. ;   zf = 0 on success      or
  933. ;   zf = 1 on error
  934. ;
  935.  
  936.                 inc     ax
  937.                 mov     dx, ax
  938.                 mov     ah, 10h
  939.                 call    cs:[XMSvect]
  940.                 cmp     ax, 1
  941.                 je      XMS_put_cont
  942.                 cmp     ax, ax
  943.                 je      XMSfail
  944.  
  945. XMS_put_cont:
  946.  
  947.                 mov     cs:[UMBseg], bx
  948.                 mov     si, 0
  949.                 mov     di, 0
  950.                 push    cs
  951.                 pop     ds
  952.                 mov     es, bx
  953.                 mov     cx, dx
  954.                 shl     cx, 3
  955.                 rep     movsw           ; copy code to UMB
  956.  
  957. XMSfail:
  958.                 ret
  959. PutCodeInUMB    endp
  960. ;----------------------------------------------------------------------------
  961. FreeUMB         proc
  962. ;
  963. ; Frees the UMB segment given
  964. ;
  965. ; call with:
  966. ;   ax - segment base of UMB
  967. ;
  968. ; returns:
  969. ;   zf = 0 on success     or
  970. ;   zf = 1 on error
  971. ;
  972.                 mov     dx, ax
  973.                 mov     ah, 11h
  974.                 call    cs:[XMSvect]
  975.                 cmp     ax, 0
  976. FreeUMBend:
  977.                 ret
  978. FreeUMB         endp
  979. ;----------------------------------------------------------------------------
  980. ;----------------------------------------------------------------------------
  981.  
  982. _TEXT           ENDS
  983. END             Begin
  984.  
  985.